﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace Xejen.Languages
{
    /// <summary>
    /// 表示语言环境管理器
    /// </summary>
    /// <creator>marc</creator>
    internal class LanguageManager : ILanguageManager
    {
        private readonly LanguageConfig _languageConfig;
        private readonly LanguageCollection _languages = new LanguageCollection();

        private ILanguage _currentLanguage;

        /// <inheritdoc/>
        public event EventHandler<ILanguage> LanguageChanged;

        /// <inheritdoc cref="LanguageManager"/>
        public LanguageManager(LanguageConfig config)
        {
            Check.NotNull(config, nameof(config));

            _languageConfig = config;

            Initialize();
        }

        /// <summary>
        /// 加载语言包
        /// </summary>
        private void Initialize()
        {
            string languagesFolderPath = _languageConfig.LanguagesFolderPath;

            List<LanguageJsonData> languageJsonDatas = new List<LanguageJsonData>();

            foreach (string filePath in Directory.GetFiles(languagesFolderPath, "*.json"))
            {
                string jsonContent = File.ReadAllText(filePath);

                LanguageJsonData languageData = JsonConvert.DeserializeObject<LanguageJsonData>(jsonContent);
                //languageData.Translations = ((JObject)JsonConvert.DeserializeObject(jsonContent)).ToObject<Dictionary<string, JToken>>();

                languageJsonDatas.Add(languageData);
            }

            languageJsonDatas.OrderBy(q => q.Order).ForEach(languageJsonData => _languages.AddIfNotContains(new KeyValuePair<string, LanguageJsonData>(languageJsonData.LanguageCode, languageJsonData)));

            Language language;
            if (_languages.Count == 0)
            {
                language = new Language(new LanguageJsonData());
            }
            else
            {
                language = new Language(_languages.FirstOrDefault(q => q.Value.Default).Value);
            }
            _currentLanguage = language;

            SetCulture();
        }

        /// <inheritdoc/>
        public void ChangeLanguage(string languageCode)
        {
            Language language;
            if (_languages.ContainsKey(languageCode))
            {
                language = new Language(_languages[languageCode]);
            }
            else
            {
                language = new Language(new LanguageJsonData());
            }

            _currentLanguage = language;

            SetCulture();

            OnLanguageChanged(this, language);
        }

        /// <inheritdoc/>
        public string[] GetLanguageCodes()
        {
            return _languages.Keys.ToArray();
        }

        /// <inheritdoc/>
        public Dictionary<string, string> GetLanguages()
        {
            Dictionary<string, string> languages = new Dictionary<string, string>();

            foreach (var language in _languages)
            {
                languages.Add(language.Value.LanguageCode, language.Value.LanguageName);
            }
            return languages;
        }

        /// <inheritdoc/>
        public ILanguage CurrentLanguage => _currentLanguage;

        private void SetCulture()
        {
            string cultureCode = _currentLanguage.LanguageCode;
            try
            {
                CultureInfo culture = new CultureInfo(cultureCode);
                Thread.CurrentThread.CurrentCulture = culture;
                Thread.CurrentThread.CurrentUICulture = culture;

                CultureInfo.DefaultThreadCurrentCulture = culture;
                CultureInfo.DefaultThreadCurrentUICulture = culture;
            }
            catch
            {
                Debug.WriteLine($"{cultureCode} 不是国际支持的标准区域语言编码，无法设定地区文化类：{nameof(CultureInfo)}");
            }
        }

        /// <inheritdoc cref="LanguageChanged"/>
        protected virtual void OnLanguageChanged(object sender, Language language)
        {
            LanguageChanged?.Invoke(sender, language);
        }
    }
}
